using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

class TestFFI
{
    [DllImport("add.dll", EntryPoint="add", CallingConvention=CallingConvention.Cdecl)]
    public static extern int add(int a, int b);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int FAdd(int a, int b);

    [DllImport("add.dll", EntryPoint="add_back", CallingConvention=CallingConvention.Cdecl)]
    public static extern int add_back(int a, int b, FAdd cb);

    const int LOOP_COUNT = 1_0000_0000;

    static void TestPInvoke()
    {
        var sw = Stopwatch.StartNew();
        int n = 0;
        for (int i = 0; i < LOOP_COUNT; i++)
            n += add(n, i);
        sw.Stop();
        Console.WriteLine("TestPInvoke_Direct  : " + n + ", " + sw.Elapsed);

        sw = Stopwatch.StartNew();
        n = 0;
        for (int i = 0; i < LOOP_COUNT; i++)
            n += add_back(n, i, (a, b) => a + b);
        sw.Stop();
        Console.WriteLine("TestPInvoke_CallBack: " + n + ", " + sw.Elapsed);
    }

    static void Main(string[] args)
    {
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine("-------- " + i);
            TestPInvoke();
        }
    }
}
